<html>
<head>
<title>NotSoSimpleSudoku</title>
<script src="jquery.js"> </script>
<script>
try{
	var cl = console.log,
			ce = console.error,
			json = JSON.stringify;
	function clj( e){
			console.log(JSON.stringify(e));
	}
} catch(e) {
	var cl=ce=json=clj=function(){};
}

function $$(id){
	return $(document.getElementById(id.replace(/#(\w+)/i,'$1')));
}

var worker = {
	worker: undefined,
	handlers:[],
	count:0,
	init: function( filename){
			this.worker = new Worker(filename||"worker.js");
			this.worker.onmessage = this.catchMessage;
	},
	request: function( cmd, args, callback, context){
			this.worker.postMessage({
					cmd:cmd,
					args:args,
					refid:this.count
			});
		   
			this.handlers.push({
					refid:this.count,
					callback:callback,
					context:context
			});
			this.count++;
	},
   
	catchMessage: function(e){
			if( e.data.cmd == "note"){
					cl( e.data.args.value);
					return;
			}
			if( e.data.cmd=="log"){
					cl( e.data.args.value);
					return;
			}
			if( e.data.cmd=="error"){
					ce( e.data.args.value);
					return;
			}if( e.data.cmd=="logerror"){
					ce( eval(e.data.args.value));
					return;
			}
			var temp= worker.handlers.filter( function( handle){
					return handle.refid == e.data.refid;
			});
			if( temp.length == 0){
					ce( "no handler found.");
					ce( e.data);
					return;
			}
			if( temp.length > 1)
					throw "Too many handlers.";
			temp[0].callback.call(temp[0].context, e.data);
	}

};

var sdkGFX = {
        zoom : 1,
        init: function(){
                worker.request("get_multiple", {values:["candidIDs","cellIDs","cellsToHouses"]}, this.createField);
                worker.request("get_multiple", {values:["cellOffsets","candidOffsets"]}, this.getOffsets);
        },
       
        createField : function(e){
                var cellsToHouses = e.args.cellsToHouses,
                        insert = $("<div></div>"),
                        cellDummy = $('<div></div>').addClass('cell'),
                        candidDummy = $('<span></span>').addClass("candid").click(function(e){
                                if( $(this).attr('only') != 'only')
                                        sdkGFX.click( this.id);
                                else
                                        sdkGFX.dblclick( this.id);
                        }).dblclick(function(e){
                                if( $(this).attr('only') != 'only')
                                        sdkGFX.dblclick( this.id);
                                else
                                        sdkGFX.dblclick( this.id);
                        });
               
                e.args.candidIDs.forEach(function(candid){
                        cellDummy.append( candidDummy.clone(true).attr('candidID',candid).attr('id','_'+candid).html(candid));
                });
               
                e.args.cellIDs.forEach( function( cellID){
                        insert.append( cellDummy
                                .clone(true)
                                .attr({
                                        id: cellID,
                                        houses: cellsToHouses[cellID].join(' ')
                                })
                                .children()
                                        .attr("id",function(){
                                                        return cellID+this.id;
                                                })
                                .end()
                                );
                });
               
                $$("sdkWrapper").empty().append(insert.children());
        },
       
        getOffsets: function(e){
                var cellOffsets = e.args.cellOffsets,
                        candidOffsets = e.args.candidOffsets,
                        style = $('<style></style>');
               
                for( var candidID in candidOffsets){
                        style.append(".candid[candidid='"+candidID+"']{\n top: "+candidOffsets[candidID].y+"%;\nleft: "+candidOffsets[candidID].x+"%;\n}\n");
                }
               
                for( var cellID in cellOffsets){
                        style.append("#"+cellID+" {\n\ttop: "+cellOffsets[cellID].y+"%;\n\tleft: "+cellOffsets[cellID].x+"%;\n}\n");
                }
               
                $$('#workerstyle').append(style.text());
        },
       
        click: function(id){
                id=id.split('_');
                worker.request("change",{value:"swap",cellID:id[0],candidID:id[1]}, this.redrawField, this);
        },
       
        dblclick: function( id){
                id=id.split('_');
                worker.request("change",{value:"only",cellID:id[0],candidID:id[1]}, this.redrawField, this);    
        },
       
        redrawField: function(e){
                e.args.value.forEach(function(cell){
                        var candids = $$(cell.id)
                                .children()
                                .attr('enabled','enabled')
                                .removeAttr('only')
                                .filter( function( candidElem){
                                        return !~cell.candids.indexOf( $(this).attr('candidid'))
                                })
                                        .removeAttr('enabled')
                                .end()
                                .filter("[enabled]");
                        if( candids.size() == 1)
                                candids.attr('only','only');
                });
        },
       
        load: function( sz){
                worker.request("init",{field: sz},this.redrawField,this);
        },
};



$(function() {
        worker.init("worker.js");      
        sdkGFX.init();
       
        $$('nakedsingle').click(function(e){
                worker.request("calc",{value:"Naked Single"}, sdkGFX.redrawField, sdkGFX);
        });
});
</script>
<style id="default" lang="CSS">

#sdkWrapper {
        position: relative;
        width: 450px;
        height: 450px;
        background: white;
}

.cell {
        border: gray thin solid;
        width: 11.22%;
        height: 11.22%;
        position: absolute;
        background: white;
}

.candid {
        font-family: monospace;
        font-size: 100%;
        position: absolute;
}


.candid.highlight {
        color: red;
}

.candid:not([enabled]) {
        color: #DDDDDD;
}



</style>
<style id="workerstyle">

</style>
<style id="randstyle">
.candid[only] {
        font-family: 'Comic Sans MS';
        font-size: 300%;
        left: 20%;
        top: -20%;
        position: absolute;
        z-index:1;
}
</style>
</head>
<body>

<div id="sdkWrapper"></div>

<br/><br/>
<input id="inputfield" type="text" value="600030008008906300003000100800167003000000000200854007009000400006308500700040001" /> <a id="loader" href="javascript:sdkGFX.load($$('inputfield').val())">Load</a>

<br/>
<a href="javascript:void(0);" id="nakedsingle">Naked Single</a>
<a href="javascript:void(0);" id="hiddensingle">Hidden Single</a>

</body>
</html>
